package http

import (
	"fmt"
	"gitee.com/captials-team/ubdframe/src/common/consts"
	"gitee.com/captials-team/ubdframe/src/common/utils"
	"gitee.com/captials-team/ubdframe/src/domain/configstc"
	"gitee.com/captials-team/ubdframe/src/domain/dto"
	"gitee.com/captials-team/ubdframe/src/domain/dto/paginate"
	"gitee.com/captials-team/ubdframe/src/domain/dto/reqdata"
	"gitee.com/captials-team/ubdframe/src/domain/dto/respdata"
	"gitee.com/captials-team/ubdframe/src/domain/interfaces"
	"gitee.com/captials-team/ubdframe/src/domain/models"
	mysqlDao "gitee.com/captials-team/ubdframe/src/infrastructure/dao/mysql"
	"gitee.com/captials-team/ubdframe/src/pkg/gin_http"
	v1log "gitee.com/captials-team/ubdframe/src/pkg/logs"
	"github.com/gin-gonic/gin"
	gocache "github.com/patrickmn/go-cache"
	"go.uber.org/dig"
	"time"
)

type AdminLogController struct {
	l v1log.ILog

	adminModel    interfaces.ItfAdminDao
	adminLogModel interfaces.ItfAdminLog

	conf *configstc.AdminAppConfig

	gin_http.ResponseController
	cache *gocache.Cache
}

func NewAdminLogController(di *dig.Scope, l v1log.ILog, conf *configstc.AdminAppConfig) *AdminLogController {
	ctr := &AdminLogController{
		l:             l,
		adminModel:    mysqlDao.NewAdminDao(conf.DBConfig),
		adminLogModel: mysqlDao.NewAdminLogDao(conf.DBConfig),

		conf: conf,

		cache: gocache.New(time.Minute, time.Minute),
	}

	return ctr
}

// SearchAdminLog godoc
// @Summary      管理员日志
// @Description  返回管理员操作日志
// @Security     AdminKeyAuth
// @Tags         admin.log
// @Accept       json
// @Produce      json
// @Param        param    body     reqdata.SearchAdminLogReq  true  "搜索参数集"
// @success 200  {object} respdata.ResponseData{data=respdata.SearchListResponse{list=[]models.AdminLog}} "获取成功"
// @Router       /mag/admin_log/search [post]
func (ctr *AdminLogController) SearchAdminLog(ctx *gin.Context) {
	var req reqdata.SearchAdminLogReq
	ctx.ShouldBind(&req)

	params := &dto.SearchAdminLogParams{
		Keywords: req.Keywords,
		Uid:      req.AdminId,
	}

	list, pager, err := ctr.adminLogModel.Search(params, &paginate.Pager{
		Page: req.Page,
		Size: req.Size,
	})
	if err != nil {
		ctr.l.Error("search err %s", err)
		ctr.Response(ctx, respdata.CSysBusy)
		return
	}

	ctr.Response(ctx, respdata.CSuccess.MData(respdata.SearchListResponse{
		List:     list,
		Paginate: *pager,
	}))
}

// CreateLog godoc
// @Summary      日志创建
// @Description  创建操作日志，可根据页面访问内容创建
// @Security     AdminKeyAuth
// @Tags         admin.log
// @Accept       json
// @Produce      json
// @Param        param    body     reqdata.SearchAdminLogReq  true  "搜索参数集"
// @success 200  {object} respdata.ResponseData{data=respdata.SearchListResponse{list=[]models.AdminLog}} "获取成功"
// @Router       /mag/admin_log/create [post]
func (ctr *AdminLogController) CreateLog(ctx *gin.Context) {
	var req reqdata.CreateLogReq
	ctx.ShouldBind(&req)

	ctr.logRecord(ctx, req.Content)

	ctr.Response(ctx, respdata.CSuccess)
}

// LogRecord 日志记录
func (ctr *AdminLogController) logRecord(ctx *gin.Context, log string) {
	//不记录日志
	if len(log) == 0 {
		return
	}
	//对应用户
	auth := gin_http.GetAuth(ctx)

	//同一用户，1分钟内与上次操作内容一致则不记录
	key := fmt.Sprintf("operate_log_%d", auth.Id)
	if pre, exist := ctr.cache.Get(key); exist && pre == log {
		ctr.l.Debug("operate log[%d] %s", auth.Id, log)
		return
	}
	ctr.cache.SetDefault(key, log)

	//登录记录
	go func(p *dto.LoginInfoParam) {
		ctr.adminLogModel.Add(&models.AdminLog{
			AdminId:  auth.Id,
			Nickname: auth.Nickname,
			Account:  auth.Account,
			Device:   p.Device,
			Log:      log,
			Ip:       p.Ip,
		})
	}(&dto.LoginInfoParam{
		Time:   time.Now(),
		Ip:     utils.GetRequestIp(ctx.Request),
		Device: ctx.Request.Header.Get("User-Agent"),
	})
}

// LogHandler 记录log(默认的log存储handler)
func (ctr *AdminLogController) LogHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		ctx.Next()

		if log, exist := ctx.Get(consts.OperateLogContextKey); exist && log != nil {
			ctr.logRecord(ctx, log.(string))
		}
	}
}
